package ldh.im.fxbase.util;

import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.scene.shape.Rectangle;
import javafx.stage.Popup;
import javafx.stage.Window;

public class MovableHelper {

    public static void movable(Region movablePane) {
        if (movablePane == null) return;
        MovableListener movableListener = new MovableListener(movablePane);
        movablePane.setOnMouseDragged(e->movableListener.moveWindow(e));
        movablePane.setOnMouseReleased(e->movableListener.endMoveWindow(e));
        movablePane.setOnDragDetected(e->movableListener.startMoveWindow(e));
    }

    public static void movable(Rectangle rectangle) {
        if (rectangle == null) return;
        MovableListener movableListener = new MovableListener(rectangle);
        rectangle.setOnMouseDragged(e->movableListener.moveWindow(e));
        rectangle.setOnMouseReleased(e->movableListener.endMoveWindow(e));
        rectangle.setOnDragDetected(e->movableListener.startMoveWindow(e));
    }

    static class MovableListener {
        private Region movablePane;
        private Rectangle rectangle;

        private Rectangle moveTrackingRect;
        private Popup moveTrackingPopup;

        private double startMoveX = -1;
        private double startMoveY = -1;
        private Boolean dragging = false;

        public MovableListener(Region movablePane) {
            this.movablePane = movablePane;
        }

        public MovableListener(Rectangle rectangle) {
            this.rectangle = rectangle;
        }

        public void startMoveWindow(MouseEvent evt) {
//            if(scene.getCursor() != Cursor.DEFAULT) return;
            double w = 0, h = 0;
            Window window = null;
            if(movablePane != null) {
                if (evt.getX() < 3 || evt.getX() > movablePane.getScene().getWindow().getWidth() - 3
                        || evt.getY() > movablePane.getScene().getWindow().getHeight() - 3) return;
                w = movablePane.getScene().getWindow().getWidth();
                h = movablePane.getScene().getWindow().getHeight();
                window = movablePane.getScene().getWindow();
            } else {
                if (evt.getX() < 3 || evt.getX() > rectangle.getWidth() - 3
                        || evt.getY() > rectangle.getHeight() - 3) return;

                w = rectangle.getWidth();
                h = rectangle.getHeight();
                window = rectangle.getScene().getWindow();
            }

            startMoveX = evt.getScreenX();
            startMoveY = evt.getScreenY();
            dragging = true;

            moveTrackingRect = new Rectangle();
            moveTrackingRect.setWidth(w);
            moveTrackingRect.setHeight(h);
            moveTrackingRect.setStyle("-fx-fill: #f3f3f4;\n" +
                    "    -fx-arc-height: 4;\n" +
                    "    -fx-arc-width: 4;" +
                    "-fx-opacity: 0.6");
//            moveTrackingRect.setLayoutX(movablePane.getLayoutX());
//            moveTrackingRect.setLayoutY(movablePane.getLayoutY());

            moveTrackingPopup = new Popup();
            moveTrackingPopup.getContent().add(moveTrackingRect);
            double stageX = window.getX();
            double stageY = window.getY();
            moveTrackingPopup.show(window, stageX, stageY);
            moveTrackingPopup.setOnHidden( (e) -> resetMoveOperation());
        }

        public void moveWindow(MouseEvent evt) {
            if (dragging) {
                double endMoveX = evt.getScreenX();
                double endMoveY = evt.getScreenY();
                Window w = getWindow();
                double stageX = w.getX();
                double stageY = w.getY();
                moveTrackingPopup.setX(stageX + (endMoveX - startMoveX));
                moveTrackingPopup.setY(stageY + (endMoveY - startMoveY));
            }
        }

        public void endMoveWindow(MouseEvent evt) {
            if (dragging) {
                double endMoveX = evt.getScreenX();
                double endMoveY = evt.getScreenY();
                Window w = getWindow();
                double stageX = w.getX();
                double stageY = w.getY();
                w.setX(stageX + (endMoveX - startMoveX));
                w.setY(stageY + (endMoveY - startMoveY));
                if (moveTrackingPopup != null) {
                    moveTrackingPopup.hide();
                    moveTrackingPopup = null;
                }
            }
            resetMoveOperation();
        }

        private void resetMoveOperation() {
            startMoveX = 0;
            startMoveY = 0;
            dragging = false;
            moveTrackingRect = null;
        }

        private Window getWindow() {
            if (movablePane != null) return movablePane.getScene().getWindow();
            return rectangle.getScene().getWindow();
        }
    }
}
